package com.myzl.quartz.task;

import cn.hutool.core.date.DatePattern;
import com.myzl.coal.domain.Device;
import com.myzl.coal.service.IDeviceService;
import com.myzl.coal.service.IPythonService;
import com.myzl.common.constant.HttpStatus;
import com.myzl.common.core.domain.AjaxResult;
import com.myzl.common.core.domain.entity.SysDictData;
import com.myzl.common.enums.DeviceTypeEnum;
import com.myzl.common.enums.DeviceGroupEnum;
import com.myzl.common.enums.DeviceStatusEnum;
import com.myzl.common.utils.DictUtils;
import com.myzl.common.utils.StringUtils;
import com.myzl.stream.pojo.ImageData;
import com.myzl.stream.service.IHIKSDKService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 摄像头任务
 * @author cew
 * @date 2022/11/22 10:11
 */
@Component("cameraTask")
@Slf4j
@Data
public class CameraTask {

    private final IDeviceService deviceService;
    private final IHIKSDKService hikSDKService;
    private final IPythonService pythonService;

    private static int taskCount = 0;

    public void cameraPicture() {
        Map<String, LocalTime> sieveRadarRuntime = getSieveRadarRuntime();
        if (sieveRadarRuntime.isEmpty()){
            return;
        }
        LocalTime currentTime = sieveRadarRuntime.get("currentTime");
        LocalTime startTime = sieveRadarRuntime.get("startTime");
        LocalTime endTime = sieveRadarRuntime.get("endTime");

        if (currentTime.isAfter(startTime) || currentTime.isBefore(endTime)){
            taskCount ++ ;
            //定时任务每30s执行一次，除以3代表一分半执行一次
            int count = 3;
            if (taskCount % count == 0) {
                List<Device> devices = deviceService.getDeviceByGroup(DeviceGroupEnum.SIEVE.getCode(), DeviceTypeEnum.CAMERA.getCode());
                for (Device device : devices) {
                    ImageData imageData = buildImageData(device);
                    AjaxResult ajaxResult = hikSDKService.saveImage(imageData);
                    cameraStatus(ajaxResult,device);
                }
                taskCount = 0;
            }
        }
    }

    public void cameraStatus() {
        List<Device> devices = deviceService.getDeviceByGroup(DeviceGroupEnum.TAPE_SCALE.getCode(), DeviceTypeEnum.CAMERA.getCode());
        for (Device device : devices) {
            ImageData imageData = buildImageData(device);
            AjaxResult ajaxResult = hikSDKService.cameraStatus(imageData);
            cameraStatus(ajaxResult,device);
        }
    }

    private ImageData buildImageData(Device device){
        List<SysDictData> hcServerPort = DictUtils.getDictCache("hc_server_port");
        short port = ObjectUtils.isEmpty(hcServerPort) ? (short)8000 : Short.parseShort(hcServerPort.get(0).getDictValue());
        ImageData imageData = new ImageData();
        imageData.setIp(device.getIp());
        imageData.setPort(port);
        imageData.setUsername(device.getUserName());
        imageData.setPassword(device.getPassword());
        imageData.setChannel(device.getChannel());
        imageData.setDeviceId(device.getId());
        return imageData;
    }

    private void cameraStatus(AjaxResult ajaxResult,Device device){
        int code = Integer.parseInt(String.valueOf(ajaxResult.get(AjaxResult.CODE_TAG)));
        if (HttpStatus.SUCCESS == code){
            device.setDeviceStatus(DeviceStatusEnum.ONLINE.getCode());
            deviceService.updateById(device);
        } else if (HttpStatus.LOGIN_FAILED == code){
            device.setDeviceStatus(DeviceStatusEnum.OFFLINE.getCode());
            deviceService.updateById(device);
        }
    }

    private String imageStatus(AjaxResult ajaxResult){
        int code = Integer.parseInt(String.valueOf(ajaxResult.get(AjaxResult.CODE_TAG)));
        if (HttpStatus.SUCCESS == code){
            return String.valueOf(ajaxResult.get(AjaxResult.DATA_TAG));
        } else{
            return "";
        }
    }

    public void aiIdentify() {
        List<String> fileNames = new ArrayList<>();
        Map<String, LocalTime> sieveRadarRuntime = getSieveRadarRuntime();
        if (sieveRadarRuntime.isEmpty()){
            return;
        }
        LocalTime currentTime = sieveRadarRuntime.get("currentTime");
        LocalTime startTime = sieveRadarRuntime.get("startTime");
        LocalTime endTime = sieveRadarRuntime.get("endTime");

        if (currentTime.isAfter(startTime) || currentTime.isBefore(endTime)){
            List<Device> devices = deviceService.getDeviceByGroup(DeviceGroupEnum.SIEVE.getCode(), DeviceTypeEnum.CAMERA.getCode());
            for (Device device : devices) {
                ImageData imageData = buildImageData(device);
                AjaxResult ajaxResult = hikSDKService.aiSaveImage(imageData);
                cameraStatus(ajaxResult,device);
                String fileName = imageStatus(ajaxResult);
                if (StringUtils.isNotEmpty(fileName)) {
                    fileNames.add(fileName);
                }
            }
        }
        // 调用图片识别后续
        if (!fileNames.isEmpty()){
            pythonService.invokePrediction(fileNames);
        }
    }

    private Map<String,LocalTime> getSieveRadarRuntime(){
        Map<String,LocalTime> sieveRadarRuntimeMap = new HashMap<>(16);
        List<SysDictData> sieveRadarRuntime = DictUtils.getDictCache("sieve_radar_runtime");
        if (StringUtils.isNull(sieveRadarRuntime)){
            return sieveRadarRuntimeMap;
        }
        LocalTime currentTime = LocalTime.now();
        LocalTime startTime = LocalTime.parse(sieveRadarRuntime.get(0).getDictValue(), DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
        LocalTime endTime = LocalTime.parse(sieveRadarRuntime.get(1).getDictValue(), DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
        sieveRadarRuntimeMap.put("currentTime",currentTime);
        sieveRadarRuntimeMap.put("startTime",startTime);
        sieveRadarRuntimeMap.put("endTime",endTime);
        return sieveRadarRuntimeMap;
    }
}
